package com.qing.common.base;

import android.annotation.SuppressLint;
import android.view.LayoutInflater;
import android.view.ViewGroup;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;

import com.qing.common.databinding.ItemEmptyLayoutBinding;
import com.qing.common.viewholder.DefaultEmptyViewHolder;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public abstract class BaseAdapter<T> extends RecyclerView.Adapter<BaseViewHolder<?, ?>> {

    public static final int ITEM_TYPE_EMPTY = 0x01;
    public static final int ITEM_TYPE_HEADER = 0x02;
    public static final int ITEM_TYPE_CONTENT = 0x03;
    public static final int ITEM_TYPE_FOOTER = 0x04;

    public static final int EMPTY_TYPE_NONE = 1;
    public static final int EMPTY_TYPE_IMAGE = 2;
    public static final int EMPTY_TYPE_TEXT = 3;

    private final List<T> mList = new ArrayList<>();
    private final boolean mHasHeader;
    private final boolean mHasFooter;
    private RecyclerView mRecyclerView;
    @EmptyViewType
    private int mEmptyType;

    private BaseAdapter<T> mOther;

    public BaseAdapter(List<T> list, @EmptyViewType int emptyType, boolean hasHeader, boolean hasFooter) {
        mList.addAll(list == null ? Collections.emptyList() : list);
        mEmptyType = emptyType;
        mHasHeader = hasHeader;
        mHasFooter = hasFooter;
    }

    public void setEmptyType(@EmptyViewType int emptyType) {
        mEmptyType = emptyType;
    }

    @NonNull
    @Override
    public final BaseViewHolder<?, ?> onCreateViewHolder(@NonNull ViewGroup parent, @ItemType int viewType) {
        switch (viewType) {
            case ITEM_TYPE_EMPTY:
                return createEmptyViewHolder(parent);
            case ITEM_TYPE_HEADER:
                return createHeaderViewHolder(parent);
            case ITEM_TYPE_CONTENT:
                return createContentViewHolder(parent);
            case ITEM_TYPE_FOOTER:
                return createFooterViewHolder(parent);
            default:
                throw new IllegalStateException("unknown view type");
        }
    }


    protected DefaultEmptyViewHolder createEmptyViewHolder(@NonNull ViewGroup parent) {
        return new DefaultEmptyViewHolder(ItemEmptyLayoutBinding.inflate(LayoutInflater.from(parent.getContext())));
    }

    protected abstract BaseViewHolder<?, ?> createHeaderViewHolder(@NonNull ViewGroup parent);

    protected abstract BaseViewHolder<?, ?> createContentViewHolder(@NonNull ViewGroup parent);

    protected abstract BaseViewHolder<?, ?> createFooterViewHolder(ViewGroup parent);

    @Override
    public void onBindViewHolder(@NonNull BaseViewHolder<?, ?> holder, int position) {
        switch (getItemViewType(position)) {
            case ITEM_TYPE_EMPTY:
                if (mRecyclerView != null) {
                    mRecyclerView.setOverScrollMode(RecyclerView.OVER_SCROLL_NEVER);
                }
                bindEmptyViewHolder((DefaultEmptyViewHolder) holder);
                break;
            case ITEM_TYPE_HEADER:
                bindHeaderViewHolder(holder);
                break;
            case ITEM_TYPE_CONTENT:
                if (mRecyclerView != null) {
                    mRecyclerView.setOverScrollMode(RecyclerView.OVER_SCROLL_ALWAYS);
                }
                bindContentViewHolder(holder, mList.get(position - (mHasHeader ? 1 : 0)));
                break;
            case ITEM_TYPE_FOOTER:
                bindFooterViewHolder(holder);
                break;
        }
    }


    protected void bindEmptyViewHolder(@NonNull DefaultEmptyViewHolder holder) {
        holder.bind(mEmptyType);
    }

    protected void bindHeaderViewHolder(@NonNull BaseViewHolder<?, ?> holder) {
        // do nothing
    }

    protected abstract void bindContentViewHolder(@NonNull BaseViewHolder<?, ?> holder, T item);

    protected void bindFooterViewHolder(BaseViewHolder<?, ?> holder) {
        // do nothing
    }

    @Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        mRecyclerView = recyclerView;
    }

    @Override
    public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onDetachedFromRecyclerView(recyclerView);
        mRecyclerView = null;
    }

    @Override
    public int getItemCount() {
        if (useEmptyView()) {
            return 1;
        }
        int size = mList.size();
        if (mHasHeader) {
            size++;
        }
        if (mHasFooter) {
            size++;
        }
        return size;
    }

    @Override
    public final @ItemType int getItemViewType(int position) {
        if (useEmptyView()) {
            return ITEM_TYPE_EMPTY;
        }
        if (mHasHeader && position == 0) {
            return ITEM_TYPE_HEADER;
        }
        if (mHasFooter && position == getItemCount() - 1) {
            return ITEM_TYPE_FOOTER;
        }
        return ITEM_TYPE_CONTENT;
    }

    public @Nullable RecyclerView getRecyclerView() {
        return mRecyclerView;
    }

    private boolean useEmptyView() {
        return mEmptyType != EMPTY_TYPE_NONE && mList.isEmpty();
    }

    /**
     * 获取其他适配器
     *
     * @return 其他适配器
     */
    protected final @Nullable BaseAdapter<T> getOther() {
        return mOther;
    }

    /**
     * 绑定其他适配器，用于多适配器联动，进行数据绑定
     *
     * @param other 其他适配器
     */
    public final void bindOther(@NonNull BaseAdapter<T> other) {
        if (other == this) throw new IllegalArgumentException("can not bind self");
        mOther = other;
    }

    public final int getDataSize() {
        return mList.size();
    }

    @NonNull
    public final List<T> getData() {
        return new ArrayList<>(mList);
    }

    @SuppressLint("NotifyDataSetChanged")
    public final void setData(@Nullable List<T> list) {
        if (!checkDataValid(list)) {
            return;
        }
        mList.clear();
        mList.addAll(list == null ? Collections.emptyList() : list);
        notifyDataSetChanged();
        if (mOther != null) {
            mOther.setData(list);
        }
    }

    protected boolean checkDataValid(List<T> list) {
        return mList.equals(list);
    }

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({EMPTY_TYPE_NONE, EMPTY_TYPE_IMAGE, EMPTY_TYPE_TEXT})
    @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
    public @interface EmptyViewType {
    }

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({ITEM_TYPE_EMPTY, ITEM_TYPE_HEADER, ITEM_TYPE_CONTENT, ITEM_TYPE_FOOTER})
    @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
    public @interface ItemType {
    }

}
